import requests
import time
import asyncio
import aiohttp
import logging
from typing import Dict, Any, Optional, Tuple
from app.core.config import settings
from app.crud.ai_workflow import error_history
from sqlalchemy.orm import Session
from .rate_limiter import (
    get_global_limiter, 
    APIType, 
    coze_request_with_retry,
    RetryableRequestError,
    NonRetryableRequestError
)

logger = logging.getLogger(__name__)

class CozeAPIService:
    def __init__(self):
        self.api_key = "pat_mx6P8HhvDJrAuJTMW4QbjLfhG3R6RUiMqmlFXHyveypRtm2oBQ6Rjhb7ixEPiBJq"
        self.base_url = "https://api.coze.cn/v3"
        self.upload_url = "https://api.coze.cn/v1/files/upload"
        self.headers = {
            'Authorization': f"Bearer {self.api_key}",
            'Content-Type': 'application/json',
        }
        self.limiter = get_global_limiter()
    
    async def validate_image_url_async(self, image_url: str) -> Tuple[bool, str]:
        """在下载/上传前校验图片 URL 可访问性，避免无效 URL 导致失败"""
        max_retries = 3
        for attempt in range(max_retries):
            try:
                # 优先 HEAD
                async with self.limiter.request(APIType.GENERAL, 'HEAD', image_url, allow_redirects=True) as resp:
                    if 200 <= resp.status < 400:
                        return True, "OK"
                    if resp.status == 405:
                        # fallback: 轻量 GET（范围请求）
                        headers = {"Range": "bytes=0-1"}
                        async with self.limiter.request(APIType.GENERAL, 'GET', image_url, headers=headers, allow_redirects=True) as resp2:
                            if 200 <= resp2.status < 400 or resp2.status in (200, 206):
                                return True, "OK"
                            return False, f"URL探测失败: {resp2.status}"
                    return False, f"URL不可访问: {resp.status}"
            except Exception as e:
                error_msg = str(e)
                # 检查是否为连接相关错误
                is_connection_error = any(keyword in error_msg.lower() for keyword in [
                    'connector is closed', 'connection', 'timeout', 'ssl',
                    'operation timed out', 'cannot connect to host', 'server disconnected'
                ])
                
                if is_connection_error and attempt < max_retries - 1:
                    wait_time = (attempt + 1) * 2  # 递增等待时间
                    print(f"🔄 URL校验连接错误，等待 {wait_time} 秒后重试 ({attempt + 1}/{max_retries}): {error_msg}")
                    await asyncio.sleep(wait_time)
                    continue
                
                # 在某些环境对 HEAD 处理不友好或事件循环问题时，尝试一次轻量 GET 兜底
                try:
                    headers = {"Range": "bytes=0-1"}
                    async with self.limiter.request(APIType.GENERAL, 'GET', image_url, headers=headers, allow_redirects=True) as resp3:
                        if 200 <= resp3.status < 400 or resp3.status in (200, 206):
                            return True, "OK"
                        return False, f"URL探测失败: {resp3.status}"
                except Exception as e2:
                    error_msg2 = str(e2)
                    is_connection_error2 = any(keyword in error_msg2.lower() for keyword in [
                        'connector is closed', 'connection', 'timeout', 'ssl',
                        'operation timed out', 'cannot connect to host', 'server disconnected'
                    ])
                    
                    if is_connection_error2 and attempt < max_retries - 1:
                        wait_time = (attempt + 1) * 2
                        print(f"🔄 URL校验GET兜底连接错误，等待 {wait_time} 秒后重试 ({attempt + 1}/{max_retries}): {error_msg2}")
                        await asyncio.sleep(wait_time)
                        break  # 跳出内层try，继续外层重试
                    
                    if attempt >= max_retries - 1:
                        return False, f"URL校验异常: {error_msg2}"
        
        return False, f"URL校验失败: 重试 {max_retries} 次后仍然连接失败"

    async def upload_image_to_coze_async(self, image_url: str) -> Tuple[bool, str]:
        """异步上传图片到Coze并获取file_id（带限流与重试 + URL 预检）"""
        # 0) URL 预检
        ok, msg = await self.validate_image_url_async(image_url)
        if not ok:
            return False, msg

        # 1) 使用限流下载图片（GENERAL）+ 重试
        download_attempts = 3
        image_data = None
        for attempt in range(download_attempts):
            try:
                async with self.limiter.request(APIType.GENERAL, 'GET', image_url, allow_redirects=True) as response:
                    if response.status == 200:
                        image_data = await response.read()
                        break
                    elif response.status in (429,) or 500 <= response.status < 600:
                        delay = min(8.0, 1.0 * (2 ** attempt))
                        await asyncio.sleep(delay)
                        continue
                    else:
                        text = await response.text()
                        return False, f"下载图片失败: {response.status}, {text}"
            except Exception as e:
                error_msg = str(e)
                # 检查是否为连接相关错误
                is_connection_error = any(keyword in error_msg.lower() for keyword in [
                    'connector is closed', 'connection', 'timeout', 'ssl',
                    'operation timed out', 'cannot connect to host', 'server disconnected'
                ])
                
                if is_connection_error and attempt < download_attempts - 1:
                    delay = min(8.0, 1.0 * (2 ** attempt))
                    print(f"🔄 图片下载连接错误，等待 {delay} 秒后重试 ({attempt + 1}/{download_attempts}): {error_msg}")
                    await asyncio.sleep(delay)
                    continue
                
                if attempt == download_attempts - 1:
                    return False, f"下载图片异常: {error_msg}"
                delay = min(8.0, 1.0 * (2 ** attempt))
                await asyncio.sleep(delay)
        if image_data is None:
            return False, "下载图片失败: 重试耗尽"

        # 2) 使用限流上传到 Coze（UPLOAD）+ 重试
        upload_attempts = 3
        for attempt in range(upload_attempts):
            try:
                import aiohttp
                upload_headers = {'Authorization': f"Bearer {self.api_key}"}
                data = aiohttp.FormData()
                data.add_field('file', image_data, filename='image.jpg', content_type='image/jpeg')

                async with self.limiter.request(
                    APIType.UPLOAD,
                    'POST',
                    self.upload_url,
                    headers=upload_headers,
                    data=data
                ) as upload_response:
                    text = await upload_response.text()
                    if upload_response.status == 200:
                        try:
                            res = await upload_response.json()
                        except Exception:
                            return False, f"上传成功但解析 JSON 失败: {text}"
                        if res.get('code') == 0:
                            return True, res['data']['id']
                        else:
                            # Coze 业务错误一般不可重试
                            return False, f"上传失败: {res.get('msg', text)}"
                    elif upload_response.status in (429,) or 500 <= upload_response.status < 600:
                        if attempt == upload_attempts - 1:
                            return False, f"上传请求失败(重试耗尽): {upload_response.status}, {text}"
                        delay = min(8.0, 1.0 * (2 ** attempt))
                        await asyncio.sleep(delay)
                        continue
                    else:
                        return False, f"上传请求失败: {upload_response.status}, {text}"
            except Exception as e:
                error_msg = str(e)
                # 检查是否为连接相关错误
                is_connection_error = any(keyword in error_msg.lower() for keyword in [
                    'connector is closed', 'connection', 'timeout', 'ssl',
                    'operation timed out', 'cannot connect to host', 'server disconnected'
                ])
                
                if is_connection_error and attempt < upload_attempts - 1:
                    delay = min(8.0, 1.0 * (2 ** attempt))
                    print(f"🔄 图片上传连接错误，等待 {delay} 秒后重试 ({attempt + 1}/{upload_attempts}): {error_msg}")
                    await asyncio.sleep(delay)
                    continue
                
                if attempt == upload_attempts - 1:
                    return False, f"上传图片异常: {error_msg}"
                delay = min(8.0, 1.0 * (2 ** attempt))
                await asyncio.sleep(delay)

        return False, "上传失败: 未知原因"

    async def create_chat_with_file_id_async(self, bot_id: str, user_id: int, file_id: str):
        # 使用 GENERAL 限流请求创建对话（带重试）
        payload = {
            "bot_id": bot_id,
            "user_id": str(user_id),
            "stream": False,
            "additional_messages": [
                {
                    "role": "user",
                    "content": f"[{{\"type\":\"image\",\"file_id\":\"{file_id}\"}}]",
                    "content_type": "object_string",
                }
            ],
        }
        attempts = 3
        for attempt in range(attempts):
            try:
                async with self.limiter.request(
                    APIType.GENERAL,
                    'POST',
                    f"{self.base_url}/chat",
                    headers=self.headers,
                    json=payload
                ) as response:
                    text = await response.text()
                    if response.status == 200:
                        res = await response.json()
                        if res.get('code') == 0:
                            return True, res['data']
                        # 业务错误不可重试
                        return False, {"error": res.get('msg', text)}
                    elif response.status in (429,) or 500 <= response.status < 600:
                        if attempt == attempts - 1:
                            return False, {"error": f"HTTP {response.status} after retries: {text}"}
                        delay = min(8.0, 1.0 * (2 ** attempt))
                        await asyncio.sleep(delay)
                        continue
                    else:
                        return False, {"error": f"HTTP {response.status}: {text}"}
            except Exception as e:
                error_msg = str(e)
                # 检查是否为连接相关错误
                is_connection_error = any(keyword in error_msg.lower() for keyword in [
                    'connector is closed', 'connection', 'timeout', 'ssl',
                    'operation timed out', 'cannot connect to host', 'server disconnected'
                ])
                
                if is_connection_error and attempt < attempts - 1:
                    delay = min(8.0, 1.0 * (2 ** attempt))
                    print(f"🔄 创建对话连接错误，等待 {delay} 秒后重试 ({attempt + 1}/{attempts}): {error_msg}")
                    await asyncio.sleep(delay)
                    continue
                
                if attempt == attempts - 1:
                    return False, {"error": f"Request exception after retries: {error_msg}"}
                delay = min(8.0, 1.0 * (2 ** attempt))
                await asyncio.sleep(delay)

        return False, {"error": "create_chat 重试耗尽"}

    async def check_chat_status_async(self, chat_id: str, conversation_id: str):
        # 使用 GENERAL 限流检查状态
        attempts = 3
        for attempt in range(attempts):
            try:
                from .rate_limiter import APIType
                async with self.limiter.request(
                    APIType.GENERAL,
                    'GET',
                    f"{self.base_url}/chat/retrieve",
                    headers=self.headers,
                    params={"chat_id": chat_id, "conversation_id": conversation_id}
                ) as response:
                    text = await response.text()
                    if response.status == 200:
                        res = await response.json()
                        if res.get('code') == 0:
                            return True, res['data']
                        return False, {"error": res.get('msg', text)}
                    elif response.status in (429,) or 500 <= response.status < 600:
                        if attempt == attempts - 1:
                            return False, {"error": f"HTTP {response.status} after retries: {text}"}
                        delay = min(4.0, 1.0 * (2 ** attempt))
                        await asyncio.sleep(delay)
                        continue
                    return False, {"error": f"HTTP {response.status}: {text}"}
            except Exception as e:
                error_msg = str(e)
                # 检查是否为连接相关错误
                is_connection_error = any(keyword in error_msg.lower() for keyword in [
                    'connector is closed', 'connection', 'timeout', 'ssl',
                    'operation timed out', 'cannot connect to host', 'server disconnected'
                ])
                
                if is_connection_error and attempt < attempts - 1:
                    delay = min(4.0, 1.0 * (2 ** attempt))
                    print(f"🔄 检查状态连接错误，等待 {delay} 秒后重试 ({attempt + 1}/{attempts}): {error_msg}")
                    await asyncio.sleep(delay)
                    continue
                
                if attempt == attempts - 1:
                    return False, {"error": f"Request exception after retries: {error_msg}"}
                delay = min(4.0, 1.0 * (2 ** attempt))
                await asyncio.sleep(delay)
        
        return False, {"error": "check_chat_status 重试耗尽"}
    
    async def get_chat_messages_async(self, chat_id: str, conversation_id: str):
        # 使用 GENERAL 限流获取消息
        attempts = 3
        for attempt in range(attempts):
            try:
                from .rate_limiter import APIType
                async with self.limiter.request(
                    APIType.GENERAL,
                    'GET',
                    f"{self.base_url}/chat/message/list",
                    headers=self.headers,
                    params={"chat_id": chat_id, "conversation_id": conversation_id}
                ) as response:
                    text = await response.text()
                    if response.status == 200:
                        res = await response.json()
                        if res.get('code') == 0:
                            return True, res['data']
                        return False, {"error": res.get('msg', text)}
                    elif response.status in (429,) or 500 <= response.status < 600:
                        if attempt == attempts - 1:
                            return False, {"error": f"HTTP {response.status} after retries: {text}"}
                        delay = min(4.0, 1.0 * (2 ** attempt))
                        await asyncio.sleep(delay)
                        continue
                    return False, {"error": f"HTTP {response.status}: {text}"}
            except Exception as e:
                error_msg = str(e)
                # 检查是否为连接相关错误
                is_connection_error = any(keyword in error_msg.lower() for keyword in [
                    'connector is closed', 'connection', 'timeout', 'ssl',
                    'operation timed out', 'cannot connect to host', 'server disconnected'
                ])
                
                if is_connection_error and attempt < attempts - 1:
                    delay = min(4.0, 1.0 * (2 ** attempt))
                    print(f"🔄 获取消息连接错误，等待 {delay} 秒后重试 ({attempt + 1}/{attempts}): {error_msg}")
                    await asyncio.sleep(delay)
                    continue
                
                if attempt == attempts - 1:
                    return False, {"error": f"Request exception after retries: {error_msg}"}
                delay = min(4.0, 1.0 * (2 ** attempt))
                await asyncio.sleep(delay)
        
        return False, {"error": "get_chat_messages 重试耗尽"}

    async def wait_for_completion_async(self, chat_id: str, conversation_id: str, 
                                       max_wait_time: int = 300, check_interval: int = 2) -> Tuple[bool, Dict[str, Any]]:
        """异步等待对话完成"""
        start_time = time.time()
        
        while time.time() - start_time < max_wait_time:
            success, result = await self.check_chat_status_async(chat_id, conversation_id)
            
            if not success:
                return False, result
            
            status = result.get('status')
            if status == 'completed':
                # 获取消息内容
                return await self.get_chat_messages_async(chat_id, conversation_id)
            elif status == 'failed':
                error_msg = result.get('last_error', {}).get('Msg', 'Chat failed')
                return False, {"error": error_msg}
            
            await asyncio.sleep(check_interval)
        
        return False, {"error": "Timeout waiting for chat completion"}
    
    async def process_image_optimization_async(self, user_id: int, image_url: str, db: Session, 
                                              workflow_id: Optional[int] = None, 
                                              step_id: Optional[int] = None) -> Tuple[bool, str]:
        """异步处理图片反推优化（完整流程）"""
        bot_id = "7512748641514438693"
        max_retries = 3
        
        for attempt in range(max_retries):
            try:
                if attempt > 0:
                    print(f"重试第 {attempt} 次...")
                    await asyncio.sleep(2 ** attempt)  # 指数退避
                    
                print("开始异步图片反推处理...")
                
                # 第一步：上传图片到Coze
                print(f"正在上传图片: {image_url}")
                upload_success, file_id_or_error = await self.upload_image_to_coze_async(image_url)
                
                if not upload_success:
                    error_msg = f"图片上传失败: {file_id_or_error}"
                    # 检查是否为连接相关错误
                    is_connection_error = any(keyword in file_id_or_error.lower() for keyword in [
                        'connector is closed', 'connection', 'timeout', 'ssl',
                        'operation timed out', 'cannot connect to host', 'server disconnected'
                    ])
                    if is_connection_error and attempt < max_retries - 1:
                        print(f"检测到连接错误，准备重试: {file_id_or_error}")
                        continue
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                file_id = file_id_or_error
                print(f"图片上传成功，file_id: {file_id}")
                
                # 第二步：创建图片对话
                success, chat_data = await self.create_chat_with_file_id_async(bot_id, user_id, file_id)
                
                if not success:
                    error_msg = f"创建Coze对话失败: {chat_data.get('error', 'Unknown error')}"
                    # 检查是否为连接相关错误
                    chat_data_str = str(chat_data)
                    is_connection_error = any(keyword in chat_data_str.lower() for keyword in [
                        'connector is closed', 'connection', 'timeout', 'ssl',
                        'operation timed out', 'cannot connect to host', 'server disconnected'
                    ])
                    if is_connection_error and attempt < max_retries - 1:
                        print(f"检测到连接错误，准备重试: {chat_data_str}")
                        continue
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                chat_id = chat_data.get('id')
                conversation_id = chat_data.get('conversation_id')
                
                if not chat_id or not conversation_id:
                    error_msg = f"Coze返回数据格式错误: {chat_data}"
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                # 第三步：异步等待完成并获取结果
                success, result = await self.wait_for_completion_async(chat_id, conversation_id)
                if not success:
                    error_msg = f"Coze对话处理失败: {result.get('error', 'Unknown error')}"
                    # 检查是否为连接相关错误
                    result_str = str(result)
                    is_connection_error = any(keyword in result_str.lower() for keyword in [
                        'connector is closed', 'connection', 'timeout', 'ssl',
                        'operation timed out', 'cannot connect to host', 'server disconnected'
                    ])
                    if is_connection_error and attempt < max_retries - 1:
                        print(f"检测到连接错误，准备重试: {result_str}")
                        continue
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                # 提取优化后的提示词
                if result and len(result) > 0:
                    optimized_prompt = result[0].get('content', '')
                    print(f"图片反推成功，提示词长度: {len(optimized_prompt)}")
                    return True, optimized_prompt
                else:
                    error_msg = "Coze返回结果为空"
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                    
            except Exception as e:
                error_msg = f"Coze API异步调用异常: {str(e)}"
                # 检查是否为连接相关错误
                exception_str = str(e)
                is_connection_error = any(keyword in exception_str.lower() for keyword in [
                    'connector is closed', 'connection', 'timeout', 'ssl',
                    'operation timed out', 'cannot connect to host', 'server disconnected'
                ])
                if is_connection_error and attempt < max_retries - 1:
                    print(f"检测到连接异常，准备重试: {exception_str}")
                    continue
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
        
        # 所有重试都失败
        final_error = "图片反推优化失败: 多次重试后仍然连接失败"
        self._log_error(db, user_id, final_error, workflow_id, step_id)
        return False, final_error

    async def process_product_tags_async(self, user_id: int, image_url: str, db: Session, 
                                        bot_id: str = "7513784190300110857",
                                        workflow_id: Optional[int] = None, 
                                        step_id: Optional[int] = None) -> Tuple[bool, str]:
        """异步处理图片反推产品标签"""
        max_retries = 3
        
        for attempt in range(max_retries):
            try:
                if attempt > 0:
                    logger.info(f"重试第 {attempt} 次...")
                    await asyncio.sleep(2 ** attempt)  # 指数退避
                    
                logger.info("开始异步图片反推产品标签...")
                
                # 第一步：上传图片到Coze
                logger.info(f"正在上传图片: {image_url}")
                upload_success, file_id_or_error = await self.upload_image_to_coze_async(image_url)
                
                if not upload_success:
                    error_msg = f"图片上传失败: {file_id_or_error}"
                    if "Server disconnected" in file_id_or_error and attempt < max_retries - 1:
                        logger.info(f"检测到连接断开，准备重试...")
                        continue
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                file_id = file_id_or_error
                logger.info(f"图片上传成功，file_id: {file_id}")
                
                # 第二步：创建图片对话
                success, chat_data = await self.create_chat_with_file_id_async(bot_id, user_id, file_id)
                
                if not success:
                    error_msg = f"创建Coze对话失败: {chat_data.get('error', 'Unknown error')}"
                    if "Server disconnected" in str(chat_data) and attempt < max_retries - 1:
                        logger.info(f"检测到连接断开，准备重试...")
                        continue
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                chat_id = chat_data.get('id')
                conversation_id = chat_data.get('conversation_id')
                
                if not chat_id or not conversation_id:
                    error_msg = f"Coze返回数据格式错误: {chat_data}"
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                # 第三步：异步等待完成并获取结果
                success, result = await self.wait_for_completion_async(chat_id, conversation_id)
                if not success:
                    error_msg = f"Coze对话处理失败: {result.get('error', 'Unknown error')}"
                    if "Server disconnected" in str(result) and attempt < max_retries - 1:
                        logger.info(f"检测到连接断开，准备重试...")
                        continue
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                
                # 提取产品标签
                if result and len(result) > 0:
                    product_tags = result[0].get('content', '')
                    logger.info(f"✅ 产品标签反推成功，内容长度: {len(product_tags)}")
                    return True, product_tags
                else:
                    error_msg = "Coze返回结果为空"
                    self._log_error(db, user_id, error_msg, workflow_id, step_id)
                    return False, error_msg
                    
            except Exception as e:
                error_msg = f"产品标签反推异常: {str(e)}"
                if "Server disconnected" in str(e) and attempt < max_retries - 1:
                    logger.info(f"检测到连接异常，准备重试: {str(e)}")
                    continue
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
        
        # 所有重试都失败
        final_error = "产品标签反推失败: 多次重试后仍然连接失败"
        self._log_error(db, user_id, final_error, workflow_id, step_id)
        return False, final_error
    
    async def process_product_description_async(self, user_id: int, image_url: str, db: Session, 
                                               bot_id: str = "7519789516224708643",
                                               workflow_id: Optional[int] = None, 
                                               step_id: Optional[int] = None) -> Tuple[bool, str]:
        """异步处理图片反推产品简介"""
        try:
            logger.info("开始异步图片反推产品简介...")
            
            # 第一步：上传图片到Coze
            logger.info(f"正在上传图片: {image_url}")
            upload_success, file_id_or_error = await self.upload_image_to_coze_async(image_url)
            
            if not upload_success:
                error_msg = f"图片上传失败: {file_id_or_error}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            file_id = file_id_or_error
            logger.info(f"图片上传成功，file_id: {file_id}")
            
            # 第二步：创建图片对话
            success, chat_data = await self.create_chat_with_file_id_async(bot_id, user_id, file_id)
            
            if not success:
                error_msg = f"创建Coze对话失败: {chat_data.get('error', 'Unknown error')}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            chat_id = chat_data.get('id')
            conversation_id = chat_data.get('conversation_id')
            
            if not chat_id or not conversation_id:
                error_msg = f"Coze返回数据格式错误: {chat_data}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            # 第三步：异步等待完成并获取结果
            success, result = await self.wait_for_completion_async(chat_id, conversation_id)
            if not success:
                error_msg = f"Coze对话处理失败: {result.get('error', 'Unknown error')}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            # 提取产品简介
            if result and len(result) > 0:
                product_description = result[0].get('content', '')
                logger.info(f"✅ 产品简介反推成功，内容长度: {len(product_description)}")
                return True, product_description
            else:
                error_msg = "Coze返回结果为空"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
                
        except Exception as e:
            error_msg = f"产品简介反推异常: {str(e)}"
            self._log_error(db, user_id, error_msg, workflow_id, step_id)
            return False, error_msg
    
    async def process_product_title_async(self, user_id: int, image_url: str, db: Session, 
                                         bot_id: str = "7519775344363716662",
                                         workflow_id: Optional[int] = None, 
                                         step_id: Optional[int] = None) -> Tuple[bool, str]:
        """异步处理图片反推产品标题"""
        try:
            logger.info("开始异步图片反推产品标题...")
            
            # 第一步：上传图片到Coze
            logger.info(f"正在上传图片: {image_url}")
            upload_success, file_id_or_error = await self.upload_image_to_coze_async(image_url)
            
            if not upload_success:
                error_msg = f"图片上传失败: {file_id_or_error}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            file_id = file_id_or_error
            logger.info(f"图片上传成功，file_id: {file_id}")
            
            # 第二步：创建图片对话
            success, chat_data = await self.create_chat_with_file_id_async(bot_id, user_id, file_id)
            
            if not success:
                error_msg = f"创建Coze对话失败: {chat_data.get('error', 'Unknown error')}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            chat_id = chat_data.get('id')
            conversation_id = chat_data.get('conversation_id')
            
            if not chat_id or not conversation_id:
                error_msg = f"Coze返回数据格式错误: {chat_data}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            # 第三步：异步等待完成并获取结果
            success, result = await self.wait_for_completion_async(chat_id, conversation_id)
            if not success:
                error_msg = f"Coze对话处理失败: {result.get('error', 'Unknown error')}"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
            
            # 提取产品标题
            if result and len(result) > 0:
                product_title = result[0].get('content', '')
                logger.info(f"✅ 产品标题反推成功，内容长度: {len(product_title)}")
                return True, product_title
            else:
                error_msg = "Coze返回结果为空"
                self._log_error(db, user_id, error_msg, workflow_id, step_id)
                return False, error_msg
                
        except Exception as e:
            error_msg = f"产品标题反推异常: {str(e)}"
            self._log_error(db, user_id, error_msg, workflow_id, step_id)
            return False, error_msg

    def _log_error(self, db: Session, user_id: int, error_message: str, 
                   workflow_id: Optional[int] = None, step_id: Optional[int] = None):
        """记录错误日志"""
        try:
            # 这里可以添加钉钉告警逻辑
            # send_msg(error_message)
            
            # 记录到数据库
            error_history.create_error(
                db=db,
                user_id=user_id,
                user_name="",  # 可以从用户表获取
                error_message=error_message,
                workflow_id=workflow_id,
                step_id=step_id,
                error_type="coze_api_error",
                api_provider="coze"
            )
        except Exception as e:
            print(f"记录错误日志失败: {str(e)}")


# 创建服务实例
coze_service = CozeAPIService()